/*
	Background.m
		based on "Background"
		by Scott Hess and Andreas Windemut (1991)
*/

#import "Background.h"
#import <dpsclient/wraps.h>
#import <appkit/Application.h>
#import <appkit/Window.h>
#import <appkit/NXImage.h>
#import <appkit/Control.h>
#import <appkit/screens.h>
#import <defaults/defaults.h>
#import <stdio.h>
#import "PSsplat.h"
#import "TVController.h"

#define  PSsplat(r, p)   _PSsplat( (r)->origin.x, (r)->origin.y, \
		(r)->size.width, (r)->size.height, (p)->x, (p)->y )

@implementation Background:View

static BOOL isfront = NO;

- free
{
	if (image != nil)
		[image free];
	[super free];
	return self;
}

- (Window *)initWinAttr
{
	Window *win;
	NXRect rect;

	[self getFrame: &rect];
	win = [[Window allocFromZone:[self zone]]
			initContent:&rect style:NX_TOKENSTYLE 
			backing:NX_BUFFERED  buttonMask:0 defer:NO];
	[win setContentView: self];
	[win useOptimizedDrawing:YES];
	[win removeFromEventMask:(NX_LMOUSEDOWNMASK | NX_LMOUSEUPMASK
		| NX_MOUSEMOVEDMASK | NX_LMOUSEDRAGGEDMASK
		| NX_MOUSEENTEREDMASK | NX_MOUSEEXITEDMASK
		| NX_KEYDOWNMASK | NX_KEYUPMASK | NX_CURSORUPDATEMASK)];
	[self toBehind: self];
	return win;
}

- setController: sender
{
	controller = sender;
	return self;
}

- (BOOL)acceptsFirstMouse
{
	return YES;
}

- toBehind:sender
{
	PSsetwindowlevel( -1, [window windowNum]);
	[window orderWindow:NX_ABOVE relativeTo:0];
	[window removeFromEventMask:NX_MOUSEDOWNMASK];
	[controller backWinFront: (isfront = NO)];
	return self;
}

- toFront:sender
{
	PSsetwindowlevel(0, [window windowNum]);
	[window orderFront:sender];
	[window addToEventMask:NX_MOUSEDOWNMASK];
	[controller backWinFront:(isfront = YES)];
	return self;
}

- mouseDown:(NXEvent *)event
{
	[[NXApp hide: self] unhide: self];
	/* These calls are needed because of illegal action of WM. */
	return [self toBehind: self];
}

- (BOOL)isFront
{
	return isfront;
}

- setImage: (NXImage *)backimage hasAlpha:(BOOL)alpha with: (int)method
{
	if (image != nil)
		[image free];
	image = [backimage copyFromZone:[self zone]];
	has_alpha = alpha;
	if (has_alpha)
		[image setBackgroundColor: NX_COLORCLEAR];
	drawMethod = method;
	return self;
}

/* Local Method */
- paintDefault
{
	const NXScreen *sc;
	const char *defcolor;
	float bg[3];

	sc = [NXApp colorScreen];
	if (sc->depth == NX_TwoBitGrayDepth
	 || sc->depth == NX_EightBitGrayDepth) {
		defcolor = NXGetDefaultValue("NeXT1", "BWBackgroundColor");
		if (!defcolor)
			PSsetgray(NX_DKGRAY);	
		else {
			sscanf(defcolor, "%f", &bg[0]);
			PSsetgray(bg[0]);	
		}
	}else {
		defcolor = NXGetDefaultValue("NeXT1", "BackgroundColor");
		if (!defcolor)
			PSsetrgbcolor(0.33333, 0.33333, 0.46667);
		else {
			sscanf(defcolor, "%f%f%f", &bg[0], &bg[1], &bg[2]);
			PSsetrgbcolor(bg[0], bg[1], bg[2]);
		}
	}
	NXRectFill(&bounds);
	return self;
}

- drawSelf:(NXRect *)rect :(int)count
{
	int mode;
	NXSize sz, screenSize;
	NXPoint pnt;

	if (image == nil)
		return self;
	[NXApp getScreenSize:&screenSize];
	[image getSize:&sz];
	if (sz.width <= 0 || sz.height <= 0)
		return self;

	mode = has_alpha ? NX_SOVER : NX_COPY;
	if (drawMethod == 0) { /* Centering */
		[self paintDefault];
		pnt.x = (screenSize.width - sz.width) / 2;
		pnt.y = (screenSize.height - sz.height) / 2;
		[image composite:mode toPoint:&pnt];
	}else {
		int i, wd, ht;
		NXRect irect;

		if (has_alpha)
			[self paintDefault];
		if (drawMethod == 1 || sz.height >= screenSize.height) {
	/* Tiling */
			wd = irect.size.width = sz.width;
			ht = irect.size.height = sz.height;
		}else {
	/* Brick Work */
			wd = (int)(sz.width) / 2;
			pnt.x = -wd, pnt.y = sz.height;
			[image composite:mode toPoint:&pnt];
			pnt.x = sz.width - wd;
			[image composite:mode toPoint:&pnt];
			wd = irect.size.width = sz.width;
			ht = irect.size.height = sz.height * 2;
		}
		pnt.x = pnt.y = 0;
		[image composite:mode toPoint:&pnt];

		irect.origin = pnt;
		for(i = wd; i < screenSize.width; i += wd) {
			pnt.x = i;
			PSsplat(&irect, &pnt);
		}
		pnt.x=0;
		irect.size.width = screenSize.width;
		for(i = ht; i < screenSize.height; i += ht) {
			pnt.y = i;
			PSsplat(&irect, &pnt);
		}
	}
	return self;
}

@end
